From dd4b7241143300d6ccc27613fc51b9f0dc19f437 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Fri, 26 Mar 2004 16:07:05 +0000 Subject: [PATCH] bitkeeper revision 1.825.4.6 (40645529V38YcP4nuYrPCmsUH5J_Bw) sched.h, irq.h, physdev.c, irq.c: Final piece of guest-PIRQ functionality in Xen. --- xen/arch/i386/irq.c | 39 +++++++++++++++++++++++++++++++++++++-- xen/common/physdev.c | 8 +------- xen/include/xen/irq.h | 1 + xen/include/xen/sched.h | 1 + 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/xen/arch/i386/irq.c b/xen/arch/i386/irq.c index 19cf5c7dc4..bb252b446d 100644 --- a/xen/arch/i386/irq.c +++ b/xen/arch/i386/irq.c @@ -941,7 +941,8 @@ int setup_irq(unsigned int irq, struct irqaction * new) #define IRQ_MAX_GUESTS 7 typedef struct { - unsigned int nr_guests; + unsigned short nr_guests; + unsigned short in_flight; struct task_struct *guest[IRQ_MAX_GUESTS]; } irq_guest_action_t; @@ -955,10 +956,39 @@ static void __do_IRQ_guest(int irq) for ( i = 0; i < action->nr_guests; i++ ) { p = action->guest[i]; + if ( !test_and_set_bit(irq, &p->pirq_mask) ) + action->in_flight++; send_guest_pirq(p, irq); } } +int pirq_guest_unmask(struct task_struct *p) +{ + irq_desc_t *desc; + int i, j, pirq; + u32 m; + shared_info_t *s = p->shared_info; + + for ( i = 0; i < 2; i++ ) + { + m = p->pirq_mask[i]; + while ( (j = ffs(m)) != 0 ) + { + m &= ~(1 << --j); + pirq = (i << 5) + j; + desc = &irq_desc[pirq]; + spin_lock_irq(&desc->lock); + if ( !test_bit(p->pirq_to_evtchn[pirq], &s->evtchn_mask[0]) && + test_and_clear_bit(pirq, &p->pirq_mask) && + (--((irq_guest_action_t *)desc->action)->in_flight == 0) ) + desc->handler->end(pirq); + spin_unlock_irq(&desc->lock); + } + } + + return 0; +} + int pirq_guest_bind(struct task_struct *p, int irq) { unsigned long flags; @@ -983,7 +1013,8 @@ int pirq_guest_bind(struct task_struct *p, int irq) goto out; action->nr_guests = 0; - + action->in_flight = 0; + desc->depth = 0; desc->status |= IRQ_GUEST; desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING); @@ -1014,6 +1045,10 @@ int pirq_guest_unbind(struct task_struct *p, int irq) action = (irq_guest_action_t *)desc->action; + if ( test_and_clear_bit(irq, &p->pirq_mask) && + (--action->in_flight == 0) ) + desc->handler->end(irq); + if ( action->nr_guests == 1 ) { desc->action = NULL; diff --git a/xen/common/physdev.c b/xen/common/physdev.c index cc2f21b172..11746785f3 100644 --- a/xen/common/physdev.c +++ b/xen/common/physdev.c @@ -564,12 +564,6 @@ static long pci_find_irq(int seg, int bus, int dev, int func, u32 *val) } -static long pci_unmask_irq(void) -{ - return 0; -} - - /* * demux hypervisor call. */ @@ -604,7 +598,7 @@ long do_physdev_op(physdev_op_t *uop) break; case PHYSDEVOP_UNMASK_IRQ: - ret = pci_unmask_irq(); + ret = pirq_guest_unmask(current); break; default: diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h index 169c4170cb..0e53cc0331 100644 --- a/xen/include/xen/irq.h +++ b/xen/include/xen/irq.h @@ -58,6 +58,7 @@ extern hw_irq_controller no_irq_type; extern void no_action(int cpl, void *dev_id, struct pt_regs *regs); struct task_struct; +extern int pirq_guest_unmask(struct task_struct *p); extern int pirq_guest_bind(struct task_struct *p, int irq); extern int pirq_guest_unbind(struct task_struct *p, int irq); diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 192c2fcc22..c12ac2ca5e 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -163,6 +163,7 @@ struct task_struct */ u16 pirq_to_evtchn[64]; u16 virq_to_evtchn[NR_VIRQS]; + u32 pirq_mask[2]; /* Physical I/O */ spinlock_t pcidev_lock; -- 2.30.2